home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / emac16ds.zip / BUFFERS.ASM < prev    next >
Assembly Source File  |  1991-08-03  |  20KB  |  832 lines

  1. ;History:757,1
  2. ;Sat Aug 19 20:49:16 1989 When creating a new buffer, try to avoid compressing memory.
  3. ;10-10-88 22:10:05 add inverse_seg to adjust_list.
  4. ;06-03-88 23:47:57 improve buffer_check
  5. ;05-26-88 23:25:49 added assumes in init_all_buffers
  6. ;05-26-88 23:24:13 remove external reference to adjust_buffers
  7. ;04-19-88 22:23:33 restore ax after returning from a buffer_free.
  8. ;03-29-88 20:59:24 store ' c' or ' e' after expand or compress.
  9. ;03-13-88 23:01:42 after doing our work, store '  ' to debug.
  10. ;12-11-87 06:52:36 add buffer_check
  11. ;12-08-87 22:52:36 add calls to store_debug
  12. ;12-06-87 00:32:51 add support for four formSegs.
  13. ;12-06-87 00:18:16 let init_forms allocate as many buffers as it wants.
  14. ;11-16-87 23:17:35 make memsize private to buffers.asm
  15. ;11-10-87 23:02:55 more work to do....
  16. ;11-10-87 21:46:38 ensure that we can treat 'data' as if it were a 'bufseg'.
  17. ;11-09-87 23:12:03 start writing buffer_free.
  18.     .xlist
  19.     include    emacs.def
  20.     include    memory.def
  21.  
  22. bufseg    segment    public
  23.  
  24.     extrn    prev_buffer: word    ;= segment of prev buffer (0 if none)
  25.     extrn    next_buffer: word    ;= segment of next buffer (0 if none)
  26.  
  27.     extrn    toptop: word
  28.     extrn    topbot: word
  29.     extrn    bottop: word
  30.     extrn    botbot: word
  31.     extrn    new_size: word
  32.  
  33. memsize        dw    ?
  34.  
  35.     extrn    bufseg_size: word
  36.  
  37. bufseg    ends
  38.  
  39.  
  40. data    segment    byte public
  41.  
  42.     extrn    lomem: byte, lomem_end: byte
  43.  
  44.     public    textseg
  45. textseg        dw    ?        ;bufseg of current text buffer.
  46. current_seg    dw    ?        ;bufseg of buffer_free caller.
  47. saveDS        dw    ?
  48. saveES        dw    ?
  49.  
  50. last_para    dw    ?        ;segment after highest buffer
  51. memory_end    dw    ?        ;segment after highest buffer right now.
  52. num_buffers    dw    ?
  53. amount_needed    dw    ?        ;amount that we need to be free.
  54. free_paras    dw    ?        ;number of free paragraphs left.
  55. insert_number    dw    ?        ;number of buffer being inserted from.
  56. insert_mark    db    ?        ;mark in buffer being inserted from.
  57.  
  58.     extrn    w1_windseg: word, w2_windseg: word    ;from redisp.asm
  59.     extrn    inverse_seg: word    ;from redisp.asm
  60.     extrn    syntax_seg: word    ;from mintform.asm
  61.     extrn    formSeg0: word        ;from mintform.asm
  62.     extrn    formSeg1: word        ;from mintform.asm
  63.     extrn    formSeg2: word        ;from mintform.asm
  64.     extrn    formSeg3: word        ;from mintform.asm
  65.  
  66. adjust_list    label    word
  67.     dw    textseg            ;have to adjust this one.
  68.     dw    current_seg
  69.     dw    w1_windseg        ;from redisp.asm, window one's buffer.
  70.     dw    w2_windseg        ;from redisp.asm, window two's buffer.
  71.     dw    inverse_seg
  72.     dw    syntax_seg
  73.     dw    formSeg0        ;from mintform.asm
  74.     dw    formSeg1        ;from mintform.asm
  75.     dw    formSeg2        ;from mintform.asm
  76.     dw    formSeg3        ;from mintform.asm
  77.     dw    saveDS
  78.     dw    saveES
  79.     dw    0
  80.  
  81. data    ends
  82.  
  83.  
  84. code    segment    byte public
  85. ;all the routines in this segment are entered with ds=data, es=data
  86.     assume    cs:code, ds:data, es:data, ss:data
  87.  
  88.     extrn    init_forms: near
  89.  
  90. comment /
  91.  
  92.     buffers:
  93.  
  94.     data
  95.     mint string
  96.     text
  97.     ...
  98.  
  99. a buffer is initially set with bottop=botbot=end of buffer.  Then the buffer
  100. is initialized.
  101. /
  102.  
  103.     public    init_all_buffers
  104. init_all_buffers:
  105. ;enter with bx=> first paragraph of unavailable memory.
  106. ;exit with cy if no buffer available.
  107.     mov    memory_end,bx        ;remember where memory ends.
  108.     mov    last_para,bx        ;remember where memory ends.
  109.     assume    ds:bufseg
  110.     mov    prev_buffer,0        ;only one buffer so far.
  111.     mov    next_buffer,0
  112.     mov    ax,offset lomem
  113.     mov    topbot,ax
  114.     mov    bottop,ax
  115.     mov    botbot,offset lomem_end
  116.     assume    ds:data
  117.     call    init_forms        ;create as many buffers as init_forms needs.
  118.     jc    init__all_buffers_1
  119.     mov    cx,offset bufseg_size
  120.     call    new_buffer        ;create a new buffer.
  121.     jc    init__all_buffers_1
  122.     assume    ds:bufseg
  123.     call    select_buffer        ;make this the current buffer.
  124.     call    init_vars$        ;init most everything
  125.     call    init_marks        ;init the rest.
  126.     clc
  127.     push    es
  128.     pop    ds
  129.     assume    ds:data
  130. init__all_buffers_1:
  131.     ret
  132.  
  133.  
  134.     public    percent_full
  135. percent_full:
  136. ;return the percent full amount in ax.
  137. ;destroy ax,cx,dx.
  138.     push    ds
  139.     mov    ds,textseg
  140.     assume    ds:bufseg
  141.     mov    ax,100
  142.     mov    cx,memsize
  143.     jcxz    percent_full_1
  144.     mov    ax,botbot        ;compute the size of the buffer
  145.     sub    ax,bottop
  146.     add    ax,topbot
  147.     sub    ax,toptop
  148.     mov    dx,0
  149.     div    cx
  150.     cmp    dx,0
  151.     je    percent_full_1
  152.     inc    ax
  153. percent_full_1:
  154.     pop    ds
  155.     assume    ds:data
  156.     ret
  157.  
  158.  
  159.     public    buffer_allocate
  160. buffer_allocate:
  161. ;entry:
  162. ;  case cx of
  163. ;    -1..-32768: report the current buffer number.
  164. ;      exit: ax=current buffer number.
  165. ;    0: create a new buffer.
  166. ;      exit: ax=new buffer number if enough memory, ax=0 otherwise.
  167. ;    1..32767:
  168. ;      entry: cx=buffer number to select, ax=0 for read/write buffer.
  169. ;      exit: ax=buffer number if it exists, ax=0 otherwise.
  170.     jcxz    buffer_allocate_2
  171.     or    cx,cx            ;if cx<0, return buffer number.
  172.     js    buffer_allocate_4
  173.     call    find_buffer
  174.     jc    buffer_allocate_5    ;buffer not found.
  175.  
  176.     push    ds
  177.     mov    ds,dx            ;get the current buffer back.
  178.     call    select_buffer
  179.     pop    ds
  180.  
  181.     jmp    buffer_allocate_4
  182.  
  183. buffer_allocate_5:
  184.     mov    ax,0            ;buffer not found.
  185.     jmp    short buffer_allocate_1
  186. buffer_allocate_2:
  187. ;create a new buffer.
  188.     mov    cx,offset bufseg_size
  189.     call    new_buffer
  190.     mov    ax,0            ;failed to create buffer - report it.
  191.     jc    buffer_allocate_1
  192.     assume    ds:bufseg
  193.     call    select_buffer        ;make this the current buffer.
  194.     call    init_vars$        ;init most everything
  195.     call    init_marks        ;init the rest.
  196.     push    es
  197.     pop    ds
  198.     assume    ds:data
  199. buffer_allocate_4:
  200. ;return the current buffer number.
  201.     mov    bx,textseg
  202.     call    buffer_number        ;return number in ax.
  203. buffer_allocate_1:
  204.     push    es
  205.     pop    ds
  206.     assume    ds:data
  207.     ret
  208.  
  209.  
  210.     public    buffer_insert
  211. buffer_insert:
  212. ;enter with al=mark, cx=buffer number.
  213. ;insert the text between point and mark from the given buffer.
  214. ;exit with nc if ok, cy if the given buffer doesn't exist, or the specified
  215. ;  text won't fit.
  216.     mov    insert_number,cx
  217.     mov    insert_mark,al
  218.  
  219.     call    find_buffer        ;find their buffer.
  220.     jc    buffer_insert_1        ;not found.
  221.  
  222. ;get the size of the inserted text, and make sure we have that much free
  223. ;space.
  224.     push    ds
  225.     mov    ds,dx
  226.     assume    ds:bufseg
  227.     mov    al,insert_mark
  228.     call    read_mark$        ;we're just interested in the count.
  229.     mov    ax,textseg        ;now free that many bytes.
  230.     call    buffer_free
  231.     pop    ds
  232.     assume    ds:data
  233.     jc    buffer_insert_1        ;go if it won't fit.
  234.  
  235. ;now find the buffer again, get the mark, and insert it.
  236.     mov    cx,insert_number
  237.     call    find_buffer        ;this should ALWAYS return nc.
  238.     mov    al,insert_mark
  239.     mov    ds,dx
  240.     assume    ds:bufseg
  241.     call    read_mark$
  242.     mov    ax,ds
  243.     mov    ds,textseg
  244.     call    insert_string$        ;this should ALWAYS return nc.
  245.     jmp    short buffer_insert_2
  246. buffer_insert_1:
  247.     stc
  248. buffer_insert_2:
  249.     push    es            ;restore ds.
  250.     pop    ds
  251.     assume    ds:data
  252.     ret
  253.  
  254.  
  255.     public    compact_buffers
  256. compact_buffers:
  257. ;exit with bx=first unused paragraph.
  258.     call    compress
  259.     push    ds
  260.     mov    ds,textseg
  261.     assume    ds:bufseg
  262. ;    mov    cx,1000h        ;give the current buffer all that
  263. ;    call    adjust_new_size        ;  we can.
  264.     call    expand
  265.     call    get_last_buffer        ;get ds = paragraph of last buffer.
  266.     call    buffer_paragraphs    ;get the size of it.
  267.     mov    bx,ds
  268.     add    bx,cx
  269.     pop    ds
  270.     mov    last_para,bx
  271.     ret
  272.  
  273.  
  274.     public    uncompact_buffers
  275. uncompact_buffers:
  276.     mov    ax,memory_end
  277.     mov    last_para,ax
  278.     ret
  279.  
  280.  
  281. compress:
  282. ;move all the buffers as low in memory as they'll go.
  283. ;exit with bx=first unused paragraph, num_buffers set to the number of buffers.
  284.     mov    ax,'*c'
  285.     call    store_debug
  286.  
  287.     push    ds
  288.     assume    ds:bufseg
  289.  
  290.     mov    num_buffers,0
  291.  
  292.     mov    ax,ds            ;get set to compress data.
  293.     mov    es,ax
  294.     mov    di,topbot        ;put the bottom at the end of the top.
  295.     mov    si,bottop        ;have to get the copy, just in case.
  296.     mov    bottop,di        ;save the new bottop.
  297.     mov    cx,botbot
  298.     sub    cx,si            ;same as sub cx,bottop
  299.     movmem
  300.     mov    botbot,di
  301.  
  302. compress_4:
  303.     inc    num_buffers
  304.     call    buffer_paragraphs
  305.     mov    new_size,cx        ;remember it for later.
  306.     cmp    next_buffer,0        ;was this the last buffer in memory?
  307.     je    compress_3    ;yes - we're done.
  308.  
  309.     call    move_buffer_lower
  310.     jmp    compress_4
  311. compress_3:
  312.     mov    bx,ds            ;get the para of the last buffer.
  313.  
  314.     call    buffer_paragraphs
  315.     add    bx,cx            ;compute the first free segment.
  316.  
  317.     pop    ds
  318.     assume    ds:data
  319.  
  320.     mov    ax,last_para        ;get the end of memory.
  321.     sub    ax,bx            ;compute the amount free.
  322.     mov    free_paras,ax        ;remember it.
  323.  
  324.     mov    ax,' c'
  325.     call    store_debug
  326.  
  327.     ret
  328.  
  329.  
  330.     public    find_buffer
  331. find_buffer:
  332. ;enter with cx=buffer number.
  333. ;exit with nc, dx set to that buffer if it exists, cy otherwise.
  334.     push    ds
  335.     assume    ds:bufseg
  336.     add    cx,4            ;allow for the forms buffer(s).
  337. find_buffer_1:
  338.     mov    dx,next_buffer
  339.     cmp    dx,0            ;at the end?
  340.     je    find_buffer_2
  341.     mov    ds,dx
  342.     loop    find_buffer_1
  343.     mov    dx,ds            ;get the current buffer back.
  344.     pop    ds
  345.     clc
  346.     ret
  347. find_buffer_2:
  348.     pop    ds
  349.     stc
  350.     ret
  351.     assume    ds:data
  352.  
  353.  
  354.     public    new_buffer
  355. new_buffer:
  356. ;create a new buffer of size cx.
  357. ;exit with cy if there's not enough memory for a new buffer, or else return
  358. ;  with ds = new buffer.
  359.  
  360. ;first we try it by compressing just the last buffer.
  361.     push    cx
  362.  
  363.     push    cx
  364.     call    compress_last        ;compress just the last buffer.
  365.     pop    cx
  366.     call    new_buffer_subr
  367.     pop    cx
  368.     jnc    new_buffer_3        ;if it worked, we're okay.
  369.  
  370.     push    cx
  371.     call    compress        ;otherwise, compress memory.
  372.     pop    cx
  373.     call    new_buffer_subr
  374. new_buffer_3:
  375.     ret
  376.  
  377.  
  378. compress_last:
  379. ;exit with the last buffer in memory compressed.
  380.  
  381. compress_last_1:
  382.     assume    ds:bufseg
  383.     mov    dx,ds            ;remember the current buffer.
  384.     mov    ax,next_buffer        ;keep going until we have the
  385.     mov    ds,ax            ;  last buffer.
  386.     or    ax,ax
  387.     jne    compress_last_1
  388.  
  389.     assume    es:bufseg
  390.     mov    ds,dx            ;get the para of the last buffer.
  391.     mov    es,dx
  392.  
  393.     mov    di,topbot
  394.     mov    si,es:bottop        ;have to get the copy, just in case.
  395.     mov    es:bottop,di        ;save the new bottop.
  396.     mov    cx,es:botbot
  397.     sub    cx,si            ;same as sub cx,bottop
  398.     movmem
  399.     mov    es:botbot,di
  400.  
  401.     mov    ax,data
  402.     mov    es,ax
  403.     mov    ds,ax
  404.     assume    ds:data, es:data
  405.  
  406.     ret
  407.  
  408.  
  409. new_buffer_subr:
  410. ;see if there's enough memory for the new buffer, and create it if there is.
  411.     push    cx
  412.  
  413. new_buffer_2:
  414.     assume    ds:bufseg
  415.     mov    dx,ds            ;remember the current buffer.
  416.     mov    ax,next_buffer        ;keep going until we have the
  417.     mov    ds,ax            ;  last buffer.
  418.     or    ax,ax
  419.     jne    new_buffer_2
  420.  
  421.     mov    ds,dx            ;get the para of the last buffer.
  422.     call    buffer_paragraphs    ;compute the size of it.
  423.     add    dx,cx            ;find the end of it.
  424.  
  425.     pop    cx
  426.     mov    ax,cx
  427.     add    ax,0fh            ;get the size rounded up.
  428.     shr    ax,1
  429.     shr    ax,1
  430.     shr    ax,1
  431.     shr    ax,1
  432.     add    ax,dx
  433.     cmp    ax,last_para        ;is there enough memory for new buffer?
  434.     jae    new_buffer_1        ;no.
  435.     mov    next_buffer,dx        ;link to the new buffer.
  436.     mov    ax,ds
  437.     mov    ds,dx
  438.     mov    prev_buffer,ax        ;link back to the old buffer.
  439.     mov    next_buffer,0        ;and no link to a new buffer.
  440.     mov    topbot,cx        ;start with an empty buffer.
  441.     mov    bottop,cx
  442.     mov    botbot,cx
  443.     clc
  444.     ret
  445. new_buffer_1:
  446.     push    es
  447.     pop    ds
  448.     assume    ds:data
  449.     stc
  450.     ret
  451.  
  452.  
  453. code    ends
  454.  
  455.  
  456. code    segment    byte public
  457. ;all the code in this segment is entered with ds=bufseg, es=data
  458.     assume    cs:code, ds:bufseg, es:data
  459.  
  460. ;the following externs are in 'memory'
  461.     extrn    init_vars$: near
  462.     extrn    insert_string$: near
  463.     extrn    read_mark$: near
  464.  
  465.  
  466. ;the following externs are in 'marks'
  467.     extrn    init_marks: near
  468.  
  469. ;the following externs are in machine dependent.
  470.     extrn    store_debug: near
  471.  
  472.     public    buffer_free, expand, adjust_all, adjust_new_size
  473.     public    adjust_segments, select_buffer, move_buffer_higher
  474.     public    move_buffer_lower, buffer_paragraphs
  475.  
  476.  
  477.     public    buffer_check
  478. buffer_check:
  479. ;exit with zr if all is ok, nz if we have a bad link.
  480.     push    ds
  481.     mov    ax,ss
  482.     mov    ds,ax
  483.     mov    cx,256
  484. buffer_check_1:
  485.     cmp    next_buffer,0        ;if we're done, exit.
  486.     je    buffer_check_2
  487.     mov    ax,ds            ;remember this buffer.
  488.  
  489.   if 0
  490.     mov    bx,botbot
  491.     add    bx,10h            ;round up to next paragraph.
  492.     rcr    bx,1            ;ensure that 65536 bytes becomes
  493.     shr    bx,1            ; 1000h paragraphs.
  494.     shr    bx,1
  495.     shr    bx,1
  496.     add    bx,ax            ;compute the next possible location
  497.     cmp    bx,next_buffer        ;  for the next buffer.
  498.     ja    buffer_check_2        ;go if we somehow overlap.
  499.   endif
  500.  
  501.     mov    ds,next_buffer        ;go to the next buffer.
  502.     cmp    ax,prev_buffer        ;does the next buffer point to us?
  503.     loope    buffer_check_1        ;keep going if we're still ok.
  504. buffer_check_2:
  505.     pop    ds
  506.     ret
  507.  
  508.  
  509.  
  510.     public    buffer_number
  511. buffer_number:
  512. ;enter with bx=paragraph of buffer.
  513. ;exit with ax=number of buffer.
  514.     push    ds
  515.     mov    ax,ss
  516.     mov    ds,ax
  517.     xor    ax,ax
  518. buffer_number_1:
  519.     mov    dx,ds
  520.     cmp    dx,bx            ;is this the one we're looking for.
  521.     je    buffer_number_2        ;yes - we've got its number.
  522.     mov    ds,next_buffer        ;get the next buffer
  523.     inc    ax
  524.     jmp    buffer_number_1
  525. buffer_number_2:
  526.     pop    ds
  527.     sub    ax,4            ;allow for the forms buffer(s).
  528.     ret
  529.  
  530.  
  531. buffer_free:
  532. ;ensure that the buffer in ax has cx bytes free.  If it doesn't, reallocate
  533. ;  memory between the buffers.  Return with cy if we cannot get enough memory.
  534. ;  return with nc, ax = new location of buffer.
  535.     mov    saveDS,ds
  536.     mov    ds,ax
  537.     assume    ds:bufseg, es:nothing
  538.     mov    ax,bottop        ;get the free space size.
  539.     sub    ax,topbot
  540.     cmp    cx,ax            ;go if we have that much space.
  541.     ja    buffer_free_1
  542.     mov    ax,ds
  543.     mov    ds,saveDS
  544.     clc
  545.     ret
  546. buffer_free_1:
  547.  
  548.     push    bx
  549.     push    cx
  550.     push    dx
  551.     push    si
  552.     push    di
  553.     mov    saveES,es
  554.  
  555.     mov    amount_needed,cx    ;remember how much we need.
  556.  
  557.     mov    current_seg,ds
  558.     mov    ax,ss
  559.     mov    ds,ax
  560.     call    compress        ;move them down all the way.
  561.     mov    ds,current_seg
  562.  
  563. ;compact buffers also sets new_size to the new total size of the buffer,
  564. ;  and sets num_buffers to the number of buffers, and sets free_paras to
  565. ;  the number of free paragraphs.
  566.     mov    cx,amount_needed    ;compute the amount for this buffer.
  567.     add    cx,0fh
  568.     rcr    cx,1            ;ensure that 65536 bytes becomes
  569.     shr    cx,1            ; 1000h paragraphs.
  570.     shr    cx,1
  571.     shr    cx,1
  572.     cmp    cx,ax            ;do we have that much?
  573.     ja    buffer_free_2        ;  no - it's hopeless.
  574.     mov    ax,new_size        ;get the current size of the buffer.
  575.     add    ax,cx            ;  add in the size that we need.
  576.     cmp    ax,1000h        ;more than a buffer can possibly hold?
  577.     jae    buffer_free_2        ;  yes - it's hopeless
  578.  
  579. ;now give our buffer the amount that it needs.
  580.     call    adjust_new_size        ;if we don't have enough memory,
  581.  
  582.     mov    ax,free_paras        ;get the free paragraphs, and divide it
  583.     mov    dx,0            ;  evenly among all the buffers.
  584.     div    num_buffers
  585.  
  586.     mov    cx,ax            ;allocate the memory evenly.
  587.     call    adjust_all        ;adjust all the buffers.
  588.  
  589.     cmp    free_paras,0        ;is there any memory left?
  590.     je    buffer_free_3        ;no - we're done allocating.
  591.  
  592.     mov    cx,65535        ;now allocate the rest of the memory.
  593.     call    adjust_all
  594. buffer_free_3:
  595.     call    expand
  596.     clc
  597.     jmp    short buffer_free_4
  598. buffer_free_2:
  599.     stc
  600. buffer_free_4:
  601.     mov    es,saveES
  602.     pop    di
  603.     pop    si
  604.     pop    dx
  605.     pop    cx
  606.     pop    bx
  607.     mov    ax,ds
  608.     mov    ds,saveDS
  609.     ret
  610.     assume    es:data
  611.  
  612.  
  613. expand:
  614. ;exit with ds=data.
  615.     mov    ax,'*e'
  616.     call    store_debug
  617.  
  618.     call    get_last_buffer
  619. ;now we have ds=paragraph of the last buffer, dx->new location for this buffer.
  620. expand_2:
  621.     mov    ax,dx            ;get the destination paragraph.
  622.     call    move_buffer_higher    ;move the buffer up.
  623.     mov    ax,prev_buffer        ;get the previous buffer.
  624.     or    ax,ax
  625.     je    expand_1        ;go if we're done.
  626.     mov    dx,ds            ;remember where we are now.
  627.     mov    ds,ax
  628.     sub    dx,new_size        ;find out where we'll be next.
  629.     jmp    expand_2
  630. expand_1:
  631.     mov    ax,' e'
  632.     call    store_debug
  633.  
  634.     ret
  635.  
  636.  
  637. get_last_buffer:
  638. ;exit with dx = paragraph of new last buffer,
  639. ;  ds = paragraph of current last buffer.
  640.     mov    dx,ss            ;add up the new sizes of the buffers.
  641.     mov    ds,dx
  642. get_last_buffer_1:
  643.     cmp    next_buffer,0        ;is this the last buffer?
  644.     je    get_last_buffer_2    ;yes - we're done.
  645.     add    dx,new_size        ;no - add in the size of this buffer,
  646.     mov    ds,next_buffer        ;and go to the next buffer.
  647.     jmp    get_last_buffer_1
  648. get_last_buffer_2:
  649.     ret
  650.  
  651.  
  652. adjust_all:
  653. ;enter with cx = amount of memory to allocate to each buffer.
  654. ;add this amount to the new size of each buffer.
  655.     push    ds
  656.     mov    ax,ss            ;get the first buffer.
  657.     mov    ds,ax
  658. adjust_all_1:
  659.     call    adjust_new_size
  660.     mov    ax,next_buffer        ;is this the last buffer?
  661.     cmp    ax,0
  662.     mov    ds,ax
  663.     jne    adjust_all_1        ;no - go do another.
  664.     pop    ds
  665.     ret
  666.  
  667.  
  668. adjust_new_size:
  669. ;enter with ds = segment whose new_size we're adjusting.
  670. ;  free_paras = the number of free paragraphs to allocate,
  671. ;  cx = number of paragraphs to allocate to the buffer in ds.
  672. ;return with cy if we don't have enough memory to allocate that many.
  673.     mov    ax,1000h        ;get the max buffer size.
  674.     sub    ax,new_size        ;subtract off the new size.
  675.     cmp    ax,cx            ;more than we want?
  676.     jb    adjust_new_size_1    ;  no - we can only give it this much.
  677.     mov    ax,cx            ;  yes - only give it as much as we want.
  678. adjust_new_size_1:
  679.     cmp    ax,free_paras        ;more than we have?
  680.     jb    adjust_new_size_2    ;  no - we can give it this much.
  681.     mov    ax,free_paras        ;  yes - only give it as much as we have.
  682. adjust_new_size_2:
  683.     add    new_size,ax
  684.     sub    free_paras,ax        ;say that we have that many fewer.
  685.     ret
  686.  
  687.  
  688. adjust_segments:
  689. ;enter with bx = current bufseg, ax = new location of that bufseg.
  690.     push    si
  691.     push    di
  692.     mov    si,offset adjust_list
  693. adjust_segments_1:
  694.     mov    di,data:[si]        ;get the next pointer.
  695.     add    si,2
  696.     or    di,di            ;exit on null.
  697.     je    adjust_segments_2
  698.     cmp    data:[di],bx        ;is this the old one?
  699.     jne    adjust_segments_1    ;no.
  700.     mov    data:[di],ax        ;yes - update with the new.
  701.     jmp    adjust_segments_1
  702. adjust_segments_2:
  703.     pop    di
  704.     pop    si
  705.     ret
  706.  
  707.  
  708. select_buffer:
  709. ;enter with ds=buffer to select.
  710.     mov    textseg,ds        ;save the new current buffer.
  711.     mov    ax,botbot
  712.     sub    ax,toptop
  713.     mov    dx,0
  714.     mov    cx,100
  715.     div    cx
  716.     mov    memsize,ax
  717.     ret
  718.  
  719.  
  720. move_buffer_higher:
  721. ;move a buffer higher in memory.
  722. ;enter with ax = new buffer location, new_size = new buffer size (in paras).
  723.     push    es
  724.     mov    bx,ds
  725.     call    adjust_segments
  726.     mov    es,ax
  727.     assume    es:bufseg
  728.  
  729.     std                ;moving from low to high, go backwards.
  730.  
  731.     mov    si,botbot        ;get the last location used in a buffer,
  732.     dec    si
  733.  
  734.     mov    di,new_size        ;compute the new last location in the
  735.     shl    di,1            ;  buffer.
  736.     shl    di,1
  737.     shl    di,1
  738.     shl    di,1
  739.     dec    di
  740.     dec    di
  741.  
  742.     mov    cx,botbot        ;compute the amount to move.
  743.     sub    cx,bottop
  744.  
  745.     mov    botbot,di
  746.     inc    botbot
  747.     rep    movsb
  748.     mov    bottop,di
  749.     inc    bottop
  750.  
  751.     mov    si,topbot        ;now move the bottom part of the buffer.
  752.     dec    si
  753.     mov    di,si
  754.     mov    cx,topbot
  755.     rep    movsb
  756.  
  757.     cld                ;now update the previous and next ptrs.
  758.     mov    si,es:prev_buffer
  759.     mov    di,es:next_buffer
  760.  
  761.     or    si,si            ;is there a previous buffer?
  762.     je    move_buffer_higher_1    ;no.
  763.     mov    ds,si
  764.     mov    next_buffer,ax        ;tell it where we are now.
  765. move_buffer_higher_1:
  766.  
  767.     or    di,di            ;is there a next buffer?
  768.     je    move_buffer_higher_2    ;no.
  769.     mov    ds,di            ;get the next buffer.
  770.     mov    prev_buffer,ax        ;tell it where we are now.
  771. move_buffer_higher_2:
  772.  
  773.     mov    ds,ax            ;and return ds = us.
  774.     pop    es
  775.     assume    es:data
  776.     ret
  777.  
  778.  
  779. move_buffer_lower:
  780. ;move a buffer lower in memory.
  781. ;enter with ds=buffer before the one to be lowered.
  782. ;exit with ds=new location of lowered buffer.
  783.     call    buffer_paragraphs
  784.  
  785.     mov    ax,ds            ;get the base of this buffer.
  786.     add    ax,cx            ;get the end of this buffer.
  787.     mov    bx,next_buffer
  788.     mov    next_buffer,ax        ;save the pointer to the next buffer.
  789.     mov    cx,ds
  790.     mov    ds,bx            ;get paragraph of buffer to move.
  791.     mov    prev_buffer,cx        ;now remember where the previous buffer is.
  792.  
  793.     call    adjust_segments
  794.  
  795.     push    es
  796.     mov    es,ax            ;move the bottom down to the new buffer.
  797.     assume    es:bufseg
  798.     mov    si,0
  799.     mov    di,si
  800.     mov    cx,topbot
  801.     movmem
  802.  
  803.     mov    si,es:bottop        ;have to get the copy, just in case.
  804.     mov    es:bottop,di        ;save the new bottop.
  805.     mov    cx,es:botbot
  806.     sub    cx,si            ;same as sub cx,bottop
  807.     movmem
  808.     mov    es:botbot,di
  809.  
  810.     pop    es
  811.     assume    es:data
  812.     mov    ds,ax            ;get new para of just moved buffer.
  813.     ret
  814.  
  815.  
  816. buffer_paragraphs:
  817. ;compute the number of paragraphs used by a buffer.
  818. ;enter with ds=buffer
  819. ;exit with cx=number of paragraphs.
  820.     mov    cx,botbot
  821.     add    cx,10h            ;round up to next paragraph.
  822.     rcr    cx,1            ;ensure that 65536 bytes becomes
  823.     shr    cx,1            ; 1000h paragraphs.
  824.     shr    cx,1
  825.     shr    cx,1
  826.     ret
  827.  
  828.  
  829. code    ends
  830.  
  831.     end
  832.